package cn.tenmg.hibernate.plus.dao;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.hibernate.SessionFactory;

import cn.tenmg.dsql.DSQLFactory;
import cn.tenmg.hibernate.plus.data.Page;

/**
 * 数据库访问对象
 * 
 * @author June wjzhao@aliyun.com
 *
 * @since 1.0.0
 */
public interface Dao {

	public static final int DEFAULTE_PAGE_SIZE = 20;

	public static final long DEFAULTE_PAGE = 1;

	/**
	 * 获取会话工厂
	 * 
	 * @return 返回会话工厂
	 */
	SessionFactory getSessionFactory();

	/**
	 * 获取Sqltool工厂
	 * 
	 * @return 返回Sqltool工厂
	 */
	DSQLFactory getDSQLFactory();

	/**
	 * 保存对象。
	 * 
	 * @param <T> 实体类
	 * @param obj 要保存的对象
	 * 
	 * @return 返回保存的对象
	 */
	<T> T save(T obj);

	/**
	 * 根据类型、主键获取对象。
	 * 
	 * @param <T>  实体类
	 * @param type 类型
	 * @param id   主键
	 * @return 返回获取的对象
	 */
	<T> T get(Class<T> type, Serializable id);

	/**
	 * 使用指定DSQL和指定参数（分别列出参数名和参数值）获取对象。
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	Object[] get(String dsql, Object... params);

	/**
	 * 使用指定DSQL和指定参数获取对象。
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数
	 * @return 返回查询到的对象
	 */
	Object[] get(String dsql, Map<String, Object> params);

	/**
	 * 使用指定类，指定DSQL和指定参数（分别列出参数名和参数值）获取对象。该方法将根据DSQL中的别名将查询结果映射为指定类对象的属性，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    实体类
	 * @param type   指定类
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	<T> T get(Class<T> type, String dsql, Object... params);

	/**
	 * 使用指定类，指定DSQL和指定参数获取对象。该方法将根据DSQL中的别名将查询结果映射为指定类对象的属性，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    实体类
	 * @param type   指定类
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数
	 * @return 返回查询到的对象
	 */
	<T> T get(Class<T> type, String dsql, Map<String, Object> params);

	/**
	 * 使用指定DSQL和指定参数（分别列出参数名和参数值）查询对象。
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	List<Object[]> query(String dsql, Object... params);

	/**
	 * 使用指定DSQL和指定参数查询对象。
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数
	 * @return 返回查询到的对象
	 */
	List<Object[]> query(String dsql, Map<String, Object> params);

	/**
	 * 使用指定类，指定DSQL和指定参数（分别列出参数名和参数值）查询对象。该方法将根据DSQL中的别名将查询结果全部映射为指定类的对象，并返回这个列表，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    实体类
	 * @param type   指定类
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	<T> List<T> query(Class<?> type, String dsql, Object... params);

	/**
	 * 使用指定类，指定DSQL和指定参数查询对象。该方法将根据DSQL中的别名将查询结果全部映射为指定类的对象，并返回这个列表，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    实体类
	 * @param type   指定类
	 * @param dsql   指定DSQL
	 * @param params 指定参数
	 * @return 返回查询到的对象
	 */
	<T> List<T> query(Class<?> type, String dsql, Map<String, Object> params);

	/**
	 * 使用指定DSQL和指定参数（分别列出参数名和参数值）查询第一列。
	 * 
	 * @param <T>    基本类型
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的第一列对象
	 */
	<T> List<T> queryFirstCol(String dsql, Object... params);

	/**
	 * 使用指定类，指定DSQL和指定参数查询对象。该方法将根据DSQL中的别名将查询结果全部映射为指定类的对象，并返回这个列表，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    基本类型
	 * @param dsql   指定DSQL
	 * @param params 指定参数
	 * @return 返回查询到的对象
	 */
	<T> List<T> queryFirstCol(String dsql, Map<String, Object> params);

	/**
	 * 使用指定DSQL和指定参数（分别列出参数名和参数值）查询唯一对象，如count查询等。
	 * 
	 * @param <T>    基本类型
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	<T> T queryUnique(String dsql, Object... params);

	/**
	 * 使用指定DSQL和指定参数查询唯一对象，如count查询等。
	 * 
	 * @param <T>    基本类型
	 * @param dsql   指定DSQL
	 * @param params 指定参数
	 * @return 返回查询到的对象
	 */
	<T> T queryUnique(String dsql, Map<String, Object> params);

	/**
	 * 使用指定类，指定DSQL和指定参数（分别列出参数名和参数值）查询唯一对象，如count查询等。该方法将根据DSQL中的别名将查询结果映射为指定类的对象 ，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    基本类型
	 * @param type   指定类
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	<T> T queryUnique(Class<T> type, String dsql, Object... params);

	/**
	 * 使用指定类，指定DSQL和指定参数（分别列出参数名和参数值）查询唯一对象，如count查询等。该方法将根据DSQL中的别名将查询结果映射为指定类的对象 ，
	 * 需要保证DSQL中的别名和指定类的属性名保持一致。
	 * 
	 * @param <T>    基本类型
	 * @param type   指定类
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象
	 */
	<T> T queryUnique(Class<T> type, String dsql, Map<String, Object> params);

	/**
	 * 使用指定DSQL，指定页码，指定页容量和指定参数（分别列出参数名和参数值）分页查询对象。
	 * 
	 * @param dsql        指定DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象并封装为Page对象
	 */
	Page<Object[]> page(String dsql, Long currentPage, Integer pageSize, Object... params);

	/**
	 * 使用指定DSQL，指定统计总数DSQL，指定页码，指定页容量和指定参数（分别列出参数名和参数值）分页查询对象。
	 * 
	 * @param dsql        指定DSQL
	 * @param cntDsql     指定统计总数DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象并封装为Page对象
	 */
	Page<Object[]> page(String dsql, String cntDsql, Long currentPage, Integer pageSize, Object... params);

	/**
	 * 使用指定DSQL，指定页码，指定页容量和指定参数分页查询对象。
	 * 
	 * @param dsql        指定DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数
	 * @return 返回查询到的对象并封装为Page对象
	 */
	Page<Object[]> page(String dsql, Long currentPage, Integer pageSize, Map<String, Object> params);

	/**
	 * 使用指定DSQL，指定统计总数DSQL，指定页码，指定页容量和指定参数分页查询对象。
	 * 
	 * @param dsql        指定DSQL
	 * @param cntDsql     指定统计总数DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数
	 * @return 返回查询到的对象并封装为Page对象
	 */
	Page<Object[]> page(String dsql, String cntDsql, Long currentPage, Integer pageSize, Map<String, Object> params);

	/**
	 * 使用指定类，指定DSQL，指定页码，指定页容量和指定参数（分别列出参数名和参数值）分页查询对象。 该方法将根据DSQL中的别名将对象映射为指定类的对象，
	 * 需要保证DSQL中的别名和对象属性名保持一致。
	 * 
	 * @param <T>         实体类
	 * @param type        指定类
	 * @param dsql        指定DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象并封装为Page对象
	 */
	<T extends Serializable> Page<T> page(Class<T> type, String dsql, Long currentPage, Integer pageSize,
			Object... params);

	/**
	 * 使用指定类，指定DSQL，指定统计总数DSQL，指定页码，指定页容量和指定参数（分别列出参数名和参数值）分页查询对象。
	 * 该方法将根据DSQL中的别名将对象映射为指定类的对象， 需要保证DSQL中的别名和对象属性名保持一致。
	 * 
	 * @param <T>         实体类
	 * @param type        指定类
	 * @param dsql        指定DSQL
	 * @param cntDsql     指定统计总数DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数（分别列出参数名和参数值）
	 * @return 返回查询到的对象并封装为Page对象
	 */
	<T extends Serializable> Page<T> page(Class<T> type, String dsql, String cntDsql, Long currentPage,
			Integer pageSize, Object... params);

	/**
	 * 使用指定类，指定DSQL，指定页码，指定页容量和指定参数分页查询对象。 该方法将根据DSQL中的别名将对象映射为指定类的对象，
	 * 需要保证DSQL中的别名和对象属性名保持一致。
	 * 
	 * @param <T>         实体类
	 * @param type        指定类
	 * @param dsql        指定DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数
	 * @return 返回查询到的对象并封装为Page对象
	 */
	<T extends Serializable> Page<T> page(Class<T> type, String dsql, Long currentPage, Integer pageSize,
			Map<String, Object> params);

	/**
	 * 使用指定类，指定DSQL，指定统计总数DSQL，指定页码，指定页容量和指定参数分页查询对象。 该方法将根据DSQL中的别名将对象映射为指定类的对象，
	 * 需要保证DSQL中的别名和对象属性名保持一致。
	 * 
	 * @param <T>         实体类
	 * @param type        指定类
	 * @param dsql        指定DSQL
	 * @param cntDsql     指定统计总数DSQL
	 * @param currentPage 指定页码
	 * @param pageSize    指定页容量
	 * @param params      指定参数
	 * @return 返回查询到的对象并封装为Page对象
	 */
	<T extends Serializable> Page<T> page(Class<T> type, String dsql, String cntDsql, Long currentPage,
			Integer pageSize, Map<String, Object> params);

	/**
	 * 更新对象。
	 * 
	 * @param <T> 实体类
	 * @param obj 要更新的对象
	 * @return 返回更新后的对象
	 */
	<T> T update(T obj);

	/**
	 * 保存或更新对象
	 * 
	 * @param <T> 实体类
	 * @param obj 要保存或更新的对象
	 * @return 返回保存或更新的对象
	 */
	<T> T saveOrUpdate(T obj);

	/**
	 * 删除对象。
	 * 
	 * @param <T> 实体类
	 * @param obj 要删除的对象
	 * @return 返回删除的对象
	 */
	<T> boolean delete(T obj);

	/**
	 * 根据类型、主键删除对象。
	 * 
	 * @param <T>  实体类
	 * @param type 类型
	 * @param id   主键
	 * @return 返回删除的对象
	 */
	<T> int delete(Class<T> type, Serializable id);

	/**
	 * 批量插入对象。
	 * 
	 * @param <T>  实体类
	 * @param list 要插入的对象列表
	 * @param size 批量刷新记录数
	 * @return 成功返回true，否则false
	 */
	<T> boolean insertBatch(List<T> list, int size);

	/**
	 * 批量更新对象。
	 * 
	 * @param <T>  实体类
	 * @param list 要更新的对象列表
	 * @param size 批量刷新记录数
	 * @return 成功返回true，否则false
	 */
	<T> boolean updateBatch(List<T> list, int size);

	/**
	 * 批量保存/更新对象。
	 * 
	 * @param <T>  实体类
	 * @param list 要保存/更新的对象列表
	 * @param size 批量刷新记录数
	 * @return 成功返回true，否则false
	 */
	<T> boolean saveOrUpdateBatch(List<T> list, int size);

	/**
	 * 执行指定DSQL和指定参数（分别列出参数名和参数值）并返回受影响行数。
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回受影响行数
	 */
	int excecute(String dsql, Object... params);

	/**
	 * 执行指定DSQL和指定参数（分别列出参数名和参数值）并返回受影响行数。
	 * 
	 * @param dsql   指定DSQL
	 * @param params 指定参数（分别列出参数名和参数值）
	 * @return 返回受影响行数
	 */
	int excecute(String dsql, Map<String, Object> params);

}
